﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace MiniPhysics
{
    class Ball
    {
        private SpriteBatch sprite;
        private Rectangle rectangle;
        private float radius;
        private Color color;
        private Vector2 position;
        private Vector2 acceleration;
        private Vector2 velocity;
        private float mass;

        public Ball(Rectangle rect, Microsoft.Xna.Framework.Game game, Color col)
        {
            rectangle = rect;
            radius = (float)rect.Width / 2.0f;
            sprite = new SpriteBatch(game.GraphicsDevice);
            position = new Vector2(rect.X, rect.Y);
            acceleration = Vector2.Zero;
            velocity = Vector2.Zero;
            color = col;
            mass = radius;
        }

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        public void draw(Texture2D texture)
        {
            sprite.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
            sprite.Draw(texture, rectangle, color);
            sprite.End();
        }

        public void update(GameTime time)
        {
            velocity += acceleration * time.ElapsedGameTime.Milliseconds / 1000;
            position += velocity * time.ElapsedGameTime.Milliseconds / 1000;
            Point point = new Point(Convert.ToInt32(position.X), Convert.ToInt32(position.Y));
            rectangle.X = point.X;
            rectangle.Y = point.Y;
        }

        public void push(Vector2 force)
        {
            acceleration = force / mass;
        }

        public void do_collision_wall(float world_width, float world_height)
        {
            if (position.X < 0)
            {
                position.X = 0;
                velocity.X = -velocity.X;
            }
            else if (position.X + 2 * radius > world_width)
            {
                position.X = world_width - 2 * radius;
                velocity.X = -velocity.X;
            }
            if (position.Y < 0)
            {
                position.Y = 0;
                velocity.Y = -velocity.Y;
            }
            else if (position.Y + 2 * radius > world_height)
            {
                position.Y = world_height - 2 * radius;
                velocity.Y = -velocity.Y;
            }
        }

        public bool do_collision_ball(Ball ball2)
        {
            Vector2 delta_pos = new Vector2(radius, radius);
            delta_pos -= new Vector2(ball2.radius, ball2.radius);

            Vector2 diff = position - ball2.position + delta_pos;
            float diff_length = diff.Length();

            float sum_rad = radius + ball2.radius;
            if (diff_length > 0 && (sum_rad > diff_length))
            {
                diff.Normalize();
                Vector2 delta_velocity_1 = velocity - ball2.velocity;
                Vector2 delta_velocity_2 = ball2.velocity - velocity;
                Vector2 penetration = (sum_rad - diff_length + 1) * diff;

                position += penetration;
                Vector2 proj_dv = Vector2.Dot(-diff, delta_velocity_2) * (-diff) * ball2.mass / mass;
                velocity += proj_dv;

                proj_dv = Vector2.Dot(diff, delta_velocity_1) * (diff) * mass / ball2.mass;
                ball2.velocity += proj_dv;
                return true;
            }
            return false;
        }
    }
}
